#include "LightPanel.h"
#include "LightProtocol.h"

typedef union{
    uint32_t code32[8];
    uint8_t  code8[32];
}codeU;
codeU codesrc;

extern  uint32_t    gloabal_time; 
extern  uint32_t    tag_code[][16];
extern  uint32_t    tag_code_dark[];

void LightPanel_Print(uint32_t *code)
{
    PANEL_CODE(0,code[0]);  
    PANEL_CODE(1,code[1]);
    PANEL_CODE(2,code[2]);
    PANEL_CODE(3,code[3]);
    PANEL_CODE(4,code[4]);
    PANEL_CODE(5,code[5]);
    PANEL_CODE(6,code[6]);
    PANEL_CODE(7,code[7]);
    PANEL_CODE(8,code[8]);
    PANEL_CODE(9,code[9]);
    PANEL_CODE(10,code[10]);
    PANEL_CODE(11,code[11]);
    PANEL_CODE(12,code[12]);
    PANEL_CODE(13,code[13]);
    PANEL_CODE(14,code[14]);
    PANEL_CODE(15,code[15]);
}

void LightPanel_SetPwm(uint8_t cycle, uint8_t duty)
{
    PANEL_PWM(cycle,duty);
}

void FM25Q16_Init()
{
    uint32_t pclk_freq=0;
    PERIPHERAL_ENABLE_ALL(SPI, 1);
    DMAC_DisableSyncRequest(SPI_TX_DMA_REQ(SPI1));
    DMAC_DisableSyncRequest(SPI_RX_DMA_REQ(SPI1));

    pclk_freq = SYS_GetPclkFreq();
    SPI_SclkDivTypeDef spi_sclk_div = pclk_freq > 240 ? SPI_CTRL_SCLK_DIV16 : pclk_freq > 120 ? SPI_CTRL_SCLK_DIV8 : SPI_CTRL_SCLK_DIV4;
    SPI_FLASH_Init(SPI1, spi_sclk_div);
    SPI_FLASH_QuadEnable(SPI1);
}
    
static void FontConvert(uint32_t* dest,uint8_t* src)
{
  dest[15] = 0;
  dest[15] = ((src[0]&0x80)>>7) |((src[2]&0x80)>>5) |((src[4]&0x80)>>3) |((src[6]&0x80)>>1) |
             ((src[0]&0x40)<<2) |((src[2]&0x40)<<4) |((src[4]&0x40)<<6) |((src[6]&0x40)<<8) |
             ((src[0]&0x20)<<11)|((src[2]&0x20)<<13)|((src[4]&0x20)<<15)|((src[6]&0x20)<<17)|
             ((src[0]&0x10)<<20)|((src[2]&0x10)<<22)|((src[4]&0x10)<<24)|((src[6]&0x10)<<26);

  dest[14] = 0;
  dest[14] = ((src[8]&0x80)>>7) |((src[10]&0x80)>>5) |((src[12]&0x80)>>3) |((src[14]&0x80)>>1) |
             ((src[8]&0x40)<<2) |((src[10]&0x40)<<4) |((src[12]&0x40)<<6) |((src[14]&0x40)<<8) |
             ((src[8]&0x20)<<11)|((src[10]&0x20)<<13)|((src[12]&0x20)<<15)|((src[14]&0x20)<<17)|
             ((src[8]&0x10)<<20)|((src[10]&0x10)<<22)|((src[12]&0x10)<<24)|((src[14]&0x10)<<26);

  dest[13] = 0;
  dest[13] = ((src[16]&0x80)>>7) |((src[18]&0x80)>>5) |((src[20]&0x80)>>3) |((src[22]&0x80)>>1) |
             ((src[16]&0x40)<<2) |((src[18]&0x40)<<4) |((src[20]&0x40)<<6) |((src[22]&0x40)<<8) |
             ((src[16]&0x20)<<11)|((src[18]&0x20)<<13)|((src[20]&0x20)<<15)|((src[22]&0x20)<<17)|
             ((src[16]&0x10)<<20)|((src[18]&0x10)<<22)|((src[20]&0x10)<<24)|((src[22]&0x10)<<26); 

  dest[12] = 0;
  dest[12] = ((src[24]&0x80)>>7) |((src[26]&0x80)>>5) |((src[28]&0x80)>>3) |((src[30]&0x80)>>1) |
             ((src[24]&0x40)<<2) |((src[26]&0x40)<<4) |((src[28]&0x40)<<6) |((src[30]&0x40)<<8) |
             ((src[24]&0x20)<<11)|((src[26]&0x20)<<13)|((src[28]&0x20)<<15)|((src[30]&0x20)<<17)|
             ((src[24]&0x10)<<20)|((src[26]&0x10)<<22)|((src[28]&0x10)<<24)|((src[30]&0x10)<<26);   

  dest[11] = 0;
  dest[11] = ((src[0]&0x08)>>3) |((src[2]&0x08)>>1) |((src[4]&0x08)<<1) |((src[6]&0x08)<<3) |
             ((src[0]&0x04)<<6) |((src[2]&0x04)<<8) |((src[4]&0x04)<<10)|((src[6]&0x04)<<12)|
             ((src[0]&0x02)<<15)|((src[2]&0x02)<<17)|((src[4]&0x02)<<19)|((src[6]&0x02)<<21)|
             ((src[0]&0x01)<<24)|((src[2]&0x01)<<26)|((src[4]&0x01)<<28)|((src[6]&0x01)<<30); 

  dest[10] = 0;
  dest[10] = ((src[8]&0x08)>>3) |((src[10]&0x08)>>1) |((src[12]&0x08)<<1) |((src[14]&0x08)<<3) |
             ((src[8]&0x04)<<6) |((src[10]&0x04)<<8) |((src[12]&0x04)<<10)|((src[14]&0x04)<<12)|
             ((src[8]&0x02)<<15)|((src[10]&0x02)<<17)|((src[12]&0x02)<<19)|((src[14]&0x02)<<21)|
             ((src[8]&0x01)<<24)|((src[10]&0x01)<<26)|((src[12]&0x01)<<28)|((src[14]&0x01)<<30);
  dest[9] = 0;
  dest[9] =  ((src[16]&0x08)>>3) |((src[18]&0x08)>>1) |((src[20]&0x08)<<1) |((src[22]&0x08)<<3) |
             ((src[16]&0x04)<<6) |((src[18]&0x04)<<8) |((src[20]&0x04)<<10)|((src[22]&0x04)<<12)|
             ((src[16]&0x02)<<15)|((src[18]&0x02)<<17)|((src[20]&0x02)<<19)|((src[22]&0x02)<<21)|
             ((src[16]&0x01)<<24)|((src[18]&0x01)<<26)|((src[20]&0x01)<<28)|((src[22]&0x01)<<30);   

  dest[8] = 0;
  dest[8] =  ((src[24]&0x08)>>3) |((src[26]&0x08)>>1) |((src[28]&0x08)<<1) |((src[30]&0x08)<<3) |
             ((src[24]&0x04)<<6) |((src[26]&0x04)<<8) |((src[28]&0x04)<<10)|((src[30]&0x04)<<12)|
             ((src[24]&0x02)<<15)|((src[26]&0x02)<<17)|((src[28]&0x02)<<19)|((src[30]&0x02)<<21)|
             ((src[24]&0x01)<<24)|((src[26]&0x01)<<26)|((src[28]&0x01)<<28)|((src[30]&0x01)<<30);       

   ////////////////////////////////////////////////////////////////////////////////////////////          
  dest[7] = 0;
  dest[7] =  ((src[1]&0x80)>>7) |((src[3]&0x80)>>5) |((src[5]&0x80)>>3) |((src[7]&0x80)>>1) |
             ((src[1]&0x40)<<2) |((src[3]&0x40)<<4) |((src[5]&0x40)<<6) |((src[7]&0x40)<<8) |
             ((src[1]&0x20)<<11)|((src[3]&0x20)<<13)|((src[5]&0x20)<<15)|((src[7]&0x20)<<17)|
             ((src[1]&0x10)<<20)|((src[3]&0x10)<<22)|((src[5]&0x10)<<24)|((src[7]&0x10)<<26);

  dest[6] = 0;
  dest[6] =  ((src[9]&0x80)>>7) |((src[11]&0x80)>>5) |((src[13]&0x80)>>3) |((src[15]&0x80)>>1) |
             ((src[9]&0x40)<<2) |((src[11]&0x40)<<4) |((src[13]&0x40)<<6) |((src[15]&0x40)<<8) |
             ((src[9]&0x20)<<11)|((src[11]&0x20)<<13)|((src[13]&0x20)<<15)|((src[15]&0x20)<<17)|
             ((src[9]&0x10)<<20)|((src[11]&0x10)<<22)|((src[13]&0x10)<<24)|((src[15]&0x10)<<26);

  dest[5] = 0;
  dest[5] =  ((src[17]&0x80)>>7) |((src[19]&0x80)>>5) |((src[21]&0x80)>>3) |((src[23]&0x80)>>1) |
             ((src[17]&0x40)<<2) |((src[19]&0x40)<<4) |((src[21]&0x40)<<6) |((src[23]&0x40)<<8) |
             ((src[17]&0x20)<<11)|((src[19]&0x20)<<13)|((src[21]&0x20)<<15)|((src[23]&0x20)<<17)|
             ((src[17]&0x10)<<20)|((src[19]&0x10)<<22)|((src[21]&0x10)<<24)|((src[23]&0x10)<<26); 

  dest[4] = 0;
  dest[4] =  ((src[25]&0x80)>>7) |((src[27]&0x80)>>5) |((src[29]&0x80)>>3) |((src[31]&0x80)>>1) |
             ((src[25]&0x40)<<2) |((src[27]&0x40)<<4) |((src[29]&0x40)<<6) |((src[31]&0x40)<<8) |
             ((src[25]&0x20)<<11)|((src[27]&0x20)<<13)|((src[29]&0x20)<<15)|((src[31]&0x20)<<17)|
             ((src[25]&0x10)<<20)|((src[27]&0x10)<<22)|((src[29]&0x10)<<24)|((src[31]&0x10)<<26);   

  dest[3] = 0;
  dest[3] =  ((src[1]&0x08)>>3) |((src[3]&0x08)>>1) |((src[5]&0x08)<<1) |((src[7]&0x08)<<3) |
             ((src[1]&0x04)<<6) |((src[3]&0x04)<<8) |((src[5]&0x04)<<10)|((src[7]&0x04)<<12)|
             ((src[1]&0x02)<<15)|((src[3]&0x02)<<17)|((src[5]&0x02)<<19)|((src[7]&0x02)<<21)|
             ((src[1]&0x01)<<24)|((src[3]&0x01)<<26)|((src[5]&0x01)<<28)|((src[7]&0x01)<<30); 

  dest[2] = 0;
  dest[2] =  ((src[9]&0x08)>>3) |((src[11]&0x08)>>1) |((src[13]&0x08)<<1) |((src[15]&0x08)<<3) |
             ((src[9]&0x04)<<6) |((src[11]&0x04)<<8) |((src[13]&0x04)<<10)|((src[15]&0x04)<<12)|
             ((src[9]&0x02)<<15)|((src[11]&0x02)<<17)|((src[13]&0x02)<<19)|((src[15]&0x02)<<21)|
             ((src[9]&0x01)<<24)|((src[11]&0x01)<<26)|((src[13]&0x01)<<28)|((src[15]&0x01)<<30);
  dest[1] = 0;
  dest[1] =  ((src[17]&0x08)>>3) |((src[19]&0x08)>>1) |((src[21]&0x08)<<1) |((src[23]&0x08)<<3) |
             ((src[17]&0x04)<<6) |((src[19]&0x04)<<8) |((src[21]&0x04)<<10)|((src[23]&0x04)<<12)|
             ((src[17]&0x02)<<15)|((src[19]&0x02)<<17)|((src[21]&0x02)<<19)|((src[23]&0x02)<<21)|
             ((src[17]&0x01)<<24)|((src[19]&0x01)<<26)|((src[21]&0x01)<<28)|((src[23]&0x01)<<30);   

  dest[0] = 0;
  dest[0] =  ((src[25]&0x08)>>3) |((src[27]&0x08)>>1) |((src[29]&0x08)<<1) |((src[31]&0x08)<<3) |
             ((src[25]&0x04)<<6) |((src[27]&0x04)<<8) |((src[29]&0x04)<<10)|((src[31]&0x04)<<12)|
             ((src[25]&0x02)<<15)|((src[27]&0x02)<<17)|((src[29]&0x02)<<19)|((src[31]&0x02)<<21)|
             ((src[25]&0x01)<<24)|((src[27]&0x01)<<26)|((src[29]&0x01)<<28)|((src[31]&0x01)<<30);
}

void Convert_GB2312_to_Code(uint32_t Gb2312Code,uint32_t* WordCode,PANEL_COLOR color)
{
   uint32_t readAddr;
   uint8_t  group;
   uint8_t  pos;

   group   = (Gb2312Code>>8)-0xB0;
   pos     = (Gb2312Code&0xFF)-0xA1;
   readAddr= (group*94+pos)<<5;
   
   if(group>71)
   {
     if(group==79)  //gb2312 0xFFxx
     {
        memset(WordCode,0,64);
     }
     else
     {
        memset(WordCode,0x55,64);
     }
   }
   else
   {
     SPI_FLASH_Read(SPI1, codesrc.code32, readAddr, 32, SPI_PHASE_MODE_QUAD, DMAC_CHANNEL6);
     FontConvert(WordCode,codesrc.code8);
   }
   Light_select_color(WordCode,color);
}

void Light_select_color(uint32_t* WordCode,PANEL_COLOR color)
{
   uint8_t  pos;
   PANEL_COLOR colorCode=0;

   if(color==YELLOW)       //协议和实际相反，兼容2号灯
   {
     colorCode = DARK;
   }
   else if(color==DARK)
   {
     colorCode = YELLOW;
   }
   else
   {
     colorCode = color;
   }

   for(pos=0;pos<16;pos++)
   {
     WordCode[pos]*=colorCode;
   }
}

//********************************************************
// 主灯盘    点阵灯运行
//********************************************************
void light_work()
{
   uint32_t period=(light.param.period[0]<<8) | light.param.period[1];
   uint32_t light_period=0;
   uint8_t  light_pos = (light.param.Tag_num)&0x7F;

   LightPanel_SetPwm(20,16);  //设置占空比，调整灯亮度
   if(light.param.mode==0)                                       //常灭
   {
      LightPanel_Print(tag_code_dark);
   }
   else if(light.param.mode==1)                                  //常亮
   {
      LightPanel_Print(tag_code[light_pos-1]);
   }
   else if(light.param.mode==2)                                  //闪烁
   {
      light_period = gloabal_time % (period<<1);                 //闪烁分为灭和亮周期
      if(light_period<=5)
        LightPanel_Print(tag_code_dark);
      else if((light_period>=period)&&(light_period<=(period+5)))
        LightPanel_Print(tag_code[light_pos-1]);
   }
   else if(light.param.mode==3)                                  //流水闪烁
   {
      light_period = gloabal_time % (period<<2);          
      
      if(light_period<period)
      {
        LightPanel_Print(tag_code[(light_pos-1)%4]);
      }
      else if( (light_period>=period) && (light_period<2*period) )
      {
        LightPanel_Print(tag_code[light_pos%4]);
      }
      else if( (light_period>=2*period) && (light_period<3*period))
      {
        LightPanel_Print(tag_code[(light_pos+1)%4]);
      }
      else if( (light_period>=3*period) && (light_period<4*period) )
      {
        LightPanel_Print(tag_code[(light_pos+2)%4]);
      }
   }
}

//********************************************************
// 副灯盘    爆闪灯运行
//********************************************************
void bling_work()
{
   uint32_t light_period=0;
   if(0 == (gloabal_time % (light.param.bling_period>>1)) )
   {
     if(0==light.param.bling_mode)  //常灭
     {
       GPIO_SetLow(LIGHT_PORT, RED_LIGHT|BLUE_LIGHT);
     }
     else if(1==light.param.bling_mode)
     {
       GPIO_SetHigh(LIGHT_PORT, RED_LIGHT|BLUE_LIGHT);
     }
     else
     {
       GPIO_Toggle(LIGHT_PORT, RED_LIGHT|BLUE_LIGHT);
     }
   }
}
